package cn.klaw.config;

import com.unfbx.chatgpt.OpenAiClient;
import com.unfbx.chatgpt.function.KeyRandomStrategy;
import com.unfbx.chatgpt.function.KeyStrategyFunction;
import com.unfbx.chatgpt.interceptor.DefaultOpenAiAuthInterceptor;
import com.unfbx.chatgpt.interceptor.OpenAiAuthInterceptor;
import cn.klaw.constants.AiConstants;
import cn.klaw.service.OpenAiService;
import cn.klaw.service.impl.DefaultOpenAiServiceImpl;
import cn.klaw.service.impl.DisabledOpenAiServiceImpl;
import cn.klaw.util.StringUtil;
import okhttp3.Authenticator;
import okhttp3.OkHttpClient;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.net.InetSocketAddress;
import java.net.PasswordAuthentication;
import java.net.Proxy;
import java.util.concurrent.TimeUnit;

/**
 * AI客户端 自动配置
 *
 *
 *
 * @date 2024/10/9 14:03
 */
@Configuration(proxyBeanMethods = false)
public class AiAutoConfiguration {

    @Bean
    @ConditionalOnMissingBean
    @ConditionalOnProperty(prefix = AiConstants.CONFIGURATION_PREFIX, name = "enabled", havingValue = "false", matchIfMissing = true)
    public OpenAiService getDisabledOpenAiService() {
        return new DisabledOpenAiServiceImpl();
    }

    @Configuration(proxyBeanMethods = false)
    @ConditionalOnProperty(prefix = AiConstants.CONFIGURATION_PREFIX, name = "enabled", havingValue = "true")
    public static class AiEnabledConfiguration{


        @Bean
        @ConfigurationProperties(prefix = AiConstants.CONFIGURATION_PREFIX)
        public AiProperties getAiProperties() {
            return new AiProperties();
        }

        @Bean
        public OpenAiService getDefaultOpenAiService(OpenAiClient openAiClient, AiProperties aiProperties) {
            return new DefaultOpenAiServiceImpl(openAiClient, aiProperties);
        }

        @Bean
        @ConditionalOnMissingBean
        public OpenAiClient getOpenAiClient(@Qualifier(AiConstants.DEFAULT_HTTP_CLIENT_BEAN_NAME) OkHttpClient okHttpClient
                , KeyStrategyFunction keyStrategyFunction, OpenAiAuthInterceptor authInterceptor, AiProperties aiProperties) {
            String apiHost = aiProperties.getApiHost();
            // 需要以 / 结尾
            if(!apiHost.isEmpty() && !apiHost.endsWith("/")){
                apiHost +="/";
            }
            // 构造openAiClient
            return OpenAiClient.builder()
                    .apiHost(apiHost)
                    .apiKey(aiProperties.getApiKey())
                    .keyStrategy(keyStrategyFunction)
                    .authInterceptor(authInterceptor)
                    .okHttpClient(okHttpClient)
                    .build();
        }

    /*@Bean
    @ConditionalOnMissingBean
    public OpenAiStreamClient getOpenAiStreamClient(@Qualifier(AiConstants.DEFAULT_HTTP_CLIENT_BEAN_NAME) OkHttpClient okHttpClient
            , KeyStrategyFunction keyStrategyFunction, OpenAiAuthInterceptor authInterceptor, AiProperties aiProperties) {
        String apiHost = aiProperties.getApiHost();
        // 需要以 / 结尾
        if(!apiHost.isEmpty() && !apiHost.endsWith("/")){
            apiHost +="/";
        }
        // 构造openAiClient
        return OpenAiStreamClient.builder()
                .apiHost(apiHost)
                .apiKey(aiProperties.getApiKey())
                .keyStrategy(keyStrategyFunction)
                .authInterceptor(authInterceptor)
                .okHttpClient(okHttpClient)
                .build();
    }*/


        /**
         * 多Key选择策略
         */
        @Bean
        @ConditionalOnMissingBean
        public KeyStrategyFunction getDefaultOpenAiKeyStrategyFunction() {
            return new KeyRandomStrategy();
        }

        /**
         * 认证拦截器
         * @see com.unfbx.chatgpt.interceptor.DynamicKeyOpenAiAuthInterceptor 动态移除无效Key
         */
        @Bean
        @ConditionalOnMissingBean
        public OpenAiAuthInterceptor getDefaultOpenAiAuthInterceptor() {
            return new DefaultOpenAiAuthInterceptor();
        }

        /**
         * 默认okhttpclient
         */
        @Bean(name = AiConstants.DEFAULT_HTTP_CLIENT_BEAN_NAME)
        @ConditionalOnMissingBean(name = AiConstants.DEFAULT_HTTP_CLIENT_BEAN_NAME)
        public OkHttpClient getDefaultOpenAiOkHttpClient(AiProperties aiProperties) {
            OkHttpClient.Builder builder = new OkHttpClient
                    .Builder();

            if(aiProperties.getProxy() != null
                    && StringUtil.isNotEmpty(aiProperties.getProxy().getHost()) && aiProperties.getProxy().getPort() != null){
                // 设置代理
                builder.proxy(new Proxy(aiProperties.getProxy().getType(), new InetSocketAddress(aiProperties.getProxy().getHost(), aiProperties.getProxy().getPort())));
                // 设置代理认证
                if(StringUtil.isNotEmpty(aiProperties.getProxy().getUsername()) && StringUtil.isNotEmpty(aiProperties.getProxy().getPassword())){
                    builder.proxyAuthenticator(Authenticator.JAVA_NET_AUTHENTICATOR);
                    java.net.Authenticator.setDefault(new java.net.Authenticator() {
                        @Override
                        protected PasswordAuthentication getPasswordAuthentication() {
                            // 返回代理的用户名和密码
                            return new PasswordAuthentication(aiProperties.getProxy().getUsername(), aiProperties.getProxy().getPassword().toCharArray());
                        }
                    });
                }
            }
        /*try {
            // 创建一个信任所有证书的 TrustManager
            final TrustManager[] trustAllCerts = new TrustManager[]{
                    new X509TrustManager() {
                        @Override
                        public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
                        }

                        @Override
                        public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
                        }

                        @Override
                        public X509Certificate[] getAcceptedIssuers() {
                            return new X509Certificate[]{};
                        }
                    }
            };

            // 安装所有信任管理器
            final SSLContext sslContext = SSLContext.getInstance("SSL");
            sslContext.init(null, trustAllCerts, new java.security.SecureRandom());

            // 创建 OkHttpClient 并配置 SSL socket factory 和 hostname verifier
            final SSLSocketFactory sslSocketFactory = sslContext.getSocketFactory();

            // 信任所有证书
            builder.sslSocketFactory(sslSocketFactory, (X509TrustManager) trustAllCerts[0]);
            builder.hostnameVerifier((hostname, session) -> true);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }*/

            return builder
                    .callTimeout(aiProperties.getTimeout(), TimeUnit.SECONDS)
                    .connectTimeout(aiProperties.getTimeout(), TimeUnit.SECONDS)
                    .writeTimeout(aiProperties.getTimeout(), TimeUnit.SECONDS)
                    .readTimeout(aiProperties.getTimeout(), TimeUnit.SECONDS)
                    .build();
        }


    }

}
